"""应用配置管理."""

from pathlib import Path
from typing import Annotated, Any, Literal

from dotenv import load_dotenv
from pydantic import AnyUrl, Field, WithJsonSchema
from pydantic_settings import BaseSettings, SettingsConfigDict

# 加载环境变量
load_dotenv()


class Settings(BaseSettings):
    """应用配置类."""

    # Settings 配置
    model_config = SettingsConfigDict(
        case_sensitive=True,
        env_file=".env",
        env_file_encoding="utf-8",
        extra="ignore",
    )

    # 通用配置
    DEBUG: Annotated[
        bool,
        Field(description="是否为调试模式"),
        WithJsonSchema({"tag": "通用配置"}),
    ] = False

    # 应用信息
    APP_NAME: Annotated[
        str,
        Field(description="应用名称"),
        WithJsonSchema({"tag": "应用信息"}),
    ] = "FastAPI Demo"
    APP_VERSION: Annotated[
        str,
        Field(description="应用版本"),
        WithJsonSchema({"tag": "应用信息"}),
    ] = "1.0.0"
    APP_DESCRIPTION: Annotated[
        str,
        Field(description="应用描述"),
        WithJsonSchema({"tag": "应用信息"}),
    ] = "基于 FastAPI 的演示项目, 遵循最佳实践"

    # 服务器配置
    LISTEN_HOST: Annotated[
        str,
        Field(description="监听主机"),
        WithJsonSchema({"tag": "服务器配置"}),
    ] = "0.0.0.0"
    LISTEN_PORT: Annotated[
        int,
        Field(gt=0, lt=65536, description="监听端口"),
        WithJsonSchema({"tag": "服务器配置"}),
    ] = 3000
    ADVERTISE_HOST: Annotated[
        str,
        Field(description="广告主机"),
        WithJsonSchema({"tag": "服务器配置"}),
    ] = "localhost"
    ADVERTISE_PORT: Annotated[
        int,
        Field(gt=0, lt=65536, description="广告端口"),
        WithJsonSchema({"tag": "服务器配置"}),
    ] = 3000

    # 日志配置
    LOG_LEVEL: Annotated[
        Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
        Field(description="日志级别"),
        WithJsonSchema({"tag": "日志配置"}),
    ] = "INFO"
    LOG_FILE: Annotated[
        Path | None,
        Field(description="日志文件"),
        WithJsonSchema({"tag": "日志配置"}),
    ] = None

    # 数据库配置
    DATABASE_URL: Annotated[
        AnyUrl,
        Field(repr=False, description="数据库URL"),
        WithJsonSchema({"tag": "数据库配置"}),
    ] = AnyUrl("postgres://postgres:123456789@localhost:5432/fastapi_demo")

    # OpenAPI 配置
    OPENAPI_ENABLED: Annotated[
        bool,
        Field(description="是否启用 OpenAPI 接口"),
        WithJsonSchema({"tag": "OpenAPI配置"}),
    ] = True
    OPENAPI_PATH: Annotated[
        str,
        Field(description="OpenAPI Json Schema 访问路径"),
        WithJsonSchema({"tag": "OpenAPI配置"}),
    ] = "/openapi.json"
    OPENAPI_DOCS_PATH: Annotated[
        str,
        Field(description="OpenAPI 文档访问路径"),
        WithJsonSchema({"tag": "OpenAPI配置"}),
    ] = "/docs"
    OPENAPI_REDOC_PATH: Annotated[
        str,
        Field(description="OpenAPI Redoc 访问路径"),
        WithJsonSchema({"tag": "OpenAPI配置"}),
    ] = "/redoc"

    # OpenTelemetry 配置
    OTEL_ENABLED: Annotated[
        bool,
        Field(description="是否启用 OpenTelemetry"),
        WithJsonSchema({"tag": "OpenTelemetry配置"}),
    ] = False

    # CORS 配置
    CORS_ORIGIN: Annotated[
        list[str],
        Field(description="CORS 允许的源"),
        WithJsonSchema({"tag": "CORS配置"}),
    ] = ["*"]
    CORS_METHODS: Annotated[
        list[str],
        Field(description="CORS 允许的方法"),
        WithJsonSchema({"tag": "CORS配置"}),
    ] = ["*"]
    CORS_ALLOWED_HEADERS: Annotated[
        list[str],
        Field(description="CORS 允许的请求头"),
        WithJsonSchema({"tag": "CORS配置"}),
    ] = ["*"]
    CORS_EXPOSE_HEADERS: Annotated[
        list[str],
        Field(description="CORS 暴露的请求头"),
        WithJsonSchema({"tag": "CORS配置"}),
    ] = ["*"]
    CORS_CREDENTIALS: Annotated[
        bool,
        Field(description="CORS 是否允许携带 Cookie"),
        WithJsonSchema({"tag": "CORS配置"}),
    ] = False
    CORS_MAX_AGE: Annotated[
        int,
        Field(description="CORS 缓存时间"),
        WithJsonSchema({"tag": "CORS配置"}),
    ] = 600

    def model_dump_safe(self) -> dict[str, Any]:
        """
        导出配置字典, 敏感字段将被替换为 '******'.

        Returns:
            处理过敏感字段的配置字典

        """
        data = self.model_dump(mode="json")

        # 获取所有标记为敏感的字段(repr=False)
        for field_name, field_info in type(self).model_fields.items():
            if field_info.repr is False and field_name in data:
                data[field_name] = "******"

        return data


settings = Settings()
"""全局配置实例"""

LISTEN_URL = f"http://{settings.LISTEN_HOST}:{settings.LISTEN_PORT}"
"""监听URL"""

ADVERTISE_URL = f"http://{settings.ADVERTISE_HOST}:{settings.ADVERTISE_PORT}"
"""广告URL"""
